/*
 * Copyright (c) 2011 Metrum Research Group LLC. All Rights Reserved.
 *
 * You may use this software under the terms of GPL v3 (http://www.gnu.org/licenses/gpl.html).
 *
 * METRUM RESEARCH GROUP LLC MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. METRUM RESEARCH GROUP LLC SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 */

package sumo;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;

public class ExpressionEvaluator {
	private static String[] prompts = SumoPropertyManager.getConfig().getStringArray("sessionpage.prompt");
	private InputStream rInputStream;
	private OutputStream OutputStream;
	private ByteArrayOutputStream Output;
	public ExpressionEvaluator() {
		super();
	}
	public InputStream getRInputStream() {
		return rInputStream;
	}
	public void setRInputStream(InputStream is) {
		this.rInputStream = is;
	}
	public OutputStream getROutputStream() {
		return OutputStream;
	}
	public void setROutputStream(OutputStream os) {
		this.OutputStream = os;
	}
	public ByteArrayOutputStream getROutput() {
		return Output;
	}
	public void setROutput(ByteArrayOutputStream baos) {
		this.Output = baos;
	}
	public String evaluate(String expression)throws IOException{
		return evaluate(expression,true);
	}
	public String evaluate(String expression, boolean echo) throws IOException {
		StringBuffer blockResult = new StringBuffer();
		BufferedReader reader = new BufferedReader(new StringReader(expression));
		try {
			String line = null;
			while ((line = reader.readLine()) != null) {
				line = line.trim();
				if (line.length() > 0) {
					String lineResult = rEvalLine(line, echo);
					if (lineResult != null && lineResult.length() > 0) {
						blockResult.append(lineResult);
					}
				}
			}
		} catch (IOException ie) {
			blockResult.append(ie.getMessage());
			blockResult.append("<br/>");
		}
		return blockResult.toString();
	}

	private void writeToOutput(String line) throws IOException {
		OutputStream.write(line.getBytes());
		OutputStream.flush();
	}
	/*public String rEvalLine(String line) throws IOException{
		String lineResult = null;
		lineResult = rEvalLine(line,true);
		return lineResult;
	}*/
	public String extract(String lineResult, String line){
		line = line.trim();
		int start = lineResult.indexOf(line);
		int len = line.length();
		if(start < 0) {};
		if(start ==0) lineResult = lineResult.substring(len);
		if(start > 0) lineResult = lineResult.substring(0,start) + lineResult.substring(start+len);
		lineResult = lineResult.trim();
		return lineResult;
	}		
	public String rEvalLine(String line, boolean echo) throws IOException {
		String lineResult = null;
		// Get current Output
		String currentOutput = Output.toString();
		//currentOutput = SumoUtils.fixROutput(currentOutput);//necessary?  As long as the old/new comparison has equivalent basis, no need to filter.
		// Now push in expression
		line = SumoUtils.fixRInput(line);
		writeToOutput(line);
		// Now read until we have a prompt
		boolean prompted = false;
		while (!prompted) {//Read the output buffer over and over until it ends with a prompt
			String newOutput = Output.toString();
			//newOutput = SumoUtils.fixROutput(newOutput);//necessary?
			for (String prompt: prompts){
				if (newOutput.length() > currentOutput.length() && newOutput.trim().endsWith(prompt)) {
					lineResult = newOutput.substring(currentOutput.length());
					//lineResult.trim();
					lineResult = lineResult.substring(0, lineResult.lastIndexOf(prompt));
					if(!echo) lineResult = extract(lineResult,line);
					lineResult = SumoUtils.fixROutput(lineResult);
					//lineResult = lineResult + "<br/>";
					prompted = true;
					break;
				}
			}
		}
		return lineResult;
	}
}